<?php

/*---------------------------------------------------------------------
封装访问memcache的接口，隔离实现,以在未装memcache扩展的环境下也可以正常运行业务代码
---------------------------------------------------------------------*/

error_reporting(E_ERROR);
include_once('dao_log.php');
include_once('dao_netapi.php');
function str_between($src,$prefix,$sufix)
{
	$prepos = strpos($src,$prefix);
	if($prepos===false)
	{
		return '';
	}
	$supos = strpos($src,$sufix,$prefos);
	if($supos===false)
	{
		return '';
	}
	return substr($src,$prepos+strlen($prefix),$supos-($prepos+strlen($prefix)));
}

class MCache
{
	static public $use_cache =true;
	static public $cache_read =true;
	static public $cache_write = true;
	static public $cache_server= 'localhost';
	static public $cache_port=11211;
	static public $memcache=null;
	static public $live_time=300; //5分钟

	static function init()
	{

		if(!function_exists('memcache_connect'))
		{
			return -1;
		}
		if(!isset(self::$memcache))
		{
			DAO_Log::debug('init mcache '. self::$cache_server);
			self::$memcache=memcache_connect(self::$cache_server,self::$cache_port);
			if(self::$memcache===false)
			{
				self::$memcache=null;
			}
			if(!isset(self::$memcache))
			{
				return false;
			}
		}
		return true;
	}

	static function set($key,&$data,$expire=-1)
	{
		if(!self::$use_cache)
		{
			return false;
		}
		if(!self::$cache_write)
		{
			return false;
		}
		if(!self::init())
		{
			return false;
		}
		if($expire<0)
		{
			$expire=self::$live_time;
		}
		self::$memcache->set($key,$data,0,$expire);
		return 0;
	}

	//--------------------
	static function get($key)
	{
		if(!self::$use_cache)
		{
			return false;
		}
		if(!self::$cache_read)
		{
			return false;
		}
		if(!self::init())
		{
			return false;
		}
		return self::$memcache->get($key);
	}

	static function inc($key,$value=1,$expire=-1)
	{
		if(!self::$use_cache)
		{
			return false;
		}
		if(!self::init())
		{
			return false;
		}
		if(self::$memcache->get($key)==false)
		{
			if($expire<0)
			{
				$expire=self::$live_time;
			}
			self::$memcache->set($key,0,$expire);
		}
		return self::$memcache->increment ($key,$value);
	}

	static function delete($key)
	{
		if(!self::$use_cache)
		{
			return false;
		}
		if(!self::$cache_read)
		{
			return false;
		}
		if(!self::init())
		{
			return false;
		}
		return self::$memcache->delete($key);
	}

	static function sendcmd($cmd,&$resp,&$msg)
	{
		trim($cmd,"\r");
		trim($cmd,"\n");
		$cmd.="\n";
		tcpsend(self::$cache_server,self::$cache_port,$cmd,$resp,true,3,$msg);
		tcpsend(self::$cache_server,self::$cache_port,"quit\r\n",$quit_resp,true,3,$msg);
	}

	static function is_value($value)
	{
		$mcache_ctrl_key=array('END','ERROR');
		$value = trim($value);
		if(strlen($value)==0)
		{
			return false;
		}
		if(array_search($value,$mcache_ctrl_key)===false)
		{

		}
		else
		{
			return false;
		}
		return true;
	}

	static function stat_items(&$items)
	{
		$cmd_stats_items = 'stats items';
		MCache::sendcmd($cmd_stats_items,$resp,$msg);
		$text_items = explode("\n",$resp);
		$prefix = 'STAT items:';
		$sufix=':number';
		foreach($text_items as $key=>$value)
		{
			if(!MCache::is_value($value))
			{
				continue;
			}
			$item = str_between($value,$prefix,$sufix);
			$item =trim($item);
			if(strlen($item)==0)
			{
				continue;
			}
			$count = trim(str_between($value,$sufix,"\r"));
			$items[$item]=$count;
		}
	}

	static function cache_dump($item_id,$count,&$result)
	{
		$cmd = "stats cachedump $item_id ".($count);
		MCache::sendcmd($cmd,$resp,$msg);
		$text_items = explode("\n",$resp);
		//ITEM groupmember::4752 [6 b; 1187923591 s]
		foreach ($text_items as $key=>$value)
		{
			if(!MCache::is_value($value))
			{
				continue;
			}
			$item_array = explode(' ',$value);
			$item['key'] = $item_array['1'];
			if(strlen($item['key'])==0)
			{
				continue;
			}
			$item['len'] = trim($item_array['2'],'[');
			$item['status'] = trim($item_array['3'],';');
			$item['time'] = $item_array['4'];
			$item['localtime'] = date('Y-m-d H:i:s',$item['time']);
			$item['type'] = trim(trim($item_array['5']),']');
			$result[$item['key']]=$item;
		}
	}

	static function all_keys()
	{
		$result=array();
		MCache::stat_items($items);
		foreach($items as $item_key=>$item_value)
		{
			MCache::cache_dump($item_key,$item_value,$result);
		}

		return $result;
	}
	static function raw_get($key)
	{
		$cmd = "get $key";
		$resp='';
		MCache::sendcmd($cmd,$resp,$msg);
		$v = str_between($resp,"\n","\nEND\r");
		return $v;
	}
};
if($argv)
{
	if($argv[1]=='ut_memcache')
	{
		if($argv[2]=='set'||$argv[2]=='getset')
		{
			$data = 'test'.date('H:i:s');
			MCache::set('test',$data);
		}

		if($argv[2]=='get'||$argv[2]=='getset')
		{
			echo 'test:'.MCache::get('test').'\r\n';
		}
		$v = MCache::inc('counter5');
		echo "counter=$v\r\n";
	}

	if($argv[1]=='mcache_get')
	{
		$result = MCache::get($argv[2]);
		var_dump($result);
	}
}
if($_GET)
{
	$request=$_GET['request'];
	if($request=='mcache_info')
	{
		ob_start();
		ob_clean();
		header('Content-Type: text/html');
		echo 'memcache info</br>';
		$resp = '';
		if(!function_exists('memcache_connect'))
		{
			$resp.= "memcache not install\r\n";
		}else{
			$resp.= 'home='.$_ENV['HOME']."\r\n";
			$resp.= 'PWD='.$_ENV['PWD']."\r\n";
			$resp.='currentuser='.get_current_user()."\r\n";
			MCache::init();
			$resp.= 'memcache= '.MCache::$memcache->getVersion()."\r\n";
			$resp.= "stat = \r\n".var_export(MCache::$memcache->getStats(),true)."\r\n<hr>";
			$resp.="ENVS\r\n".var_export($_ENV,true)."\r\n<hr>";
			$resp.="SERVER\r\n".var_export($_SERVER,true)."\r\n<hr>";
			$resp.="REQUEST\r\n".var_export($_REQUEST,true)."\r\n<hr>";
		}
		$resp = nl2br($resp);
		echo $resp;
		ob_flush();
	}
}
?>